package org.snia.server.rs;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.Encoded;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.HEAD;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.UriInfo;

import org.apache.commons.lang.StringUtils;
import org.snia.cdmi.ErrorCodes;
import org.snia.cdmi.Headers;
import org.snia.cdmi.QueryParameters;
import org.snia.cdmi.exception.BadRequestException;
import org.snia.cdmi.model.AccessControlList;
import org.snia.cdmi.model.DataObject;
import org.snia.cdmi.model.DataObjectProperties;
import org.snia.cdmi.model.Grantee;
import org.snia.cdmi.model.InputDataObject;
import org.snia.cdmi.model.KeyGrantee;
import org.snia.cdmi.model.MetaDataObject;
import org.snia.cdmi.model.Permission;
import org.snia.cdmi.model.StoreClass;
import org.snia.cdmi.model.ZipMode;
import org.snia.server.dispatcher.Dispatcher;
import org.snia.server.dispatcher.DispatcherFactory;
import org.snia.util.MediaTypes;

@Path("/{container}/{objectUri:.*}")
@Encoded
public class ObjectResource extends AbstractResource {

	private final static Dispatcher compositor = DispatcherFactory.create();

	private final static String[] SIGNED_PARAMETERS = { "acl", "metadata",
			"task" };

	@Context
	private UriInfo ui;

	@PUT
	@Produces(MediaType.TEXT_XML)
	public Response putResource(@PathParam("container") String container,
			@PathParam("objectUri") String objectUri,
			@Context HttpHeaders headers, byte[] context) {
		MultivaluedMap<String, String> params = ui.getQueryParameters();
		String option = params.getFirst("acl");
		if (option != null) {
			return this.setAccessControlPolicy(container, objectUri, context);
		}
		option = params.getFirst("metadata");
		if (option != null) {
			return this.setUserMetadata(container, objectUri, headers);
		}
		
		
		String source = (headers.getRequestHeader(Headers.CDMI_COPY_SOURCE) == null) ? null
				: headers.getRequestHeader(Headers.CDMI_COPY_SOURCE).get(0);
		boolean replaceFlag = (headers
				.getRequestHeader(Headers.CDMI_METADATA_REPLACE) == null) ? null
				: Boolean.valueOf(headers.getRequestHeader(
						Headers.CDMI_METADATA_REPLACE).get(0));

		return copyObject(container, objectUri, source, replaceFlag);
	}

	@GET
	@Consumes(MediaType.TEXT_XML)
	public Response getResource(@PathParam("container") String container,
			@PathParam("objectUri") String objectUri,
			@Context HttpHeaders headers, byte[] context) {
		MultivaluedMap<String, String> params = ui.getQueryParameters();
		String option = params.getFirst("acl");
		if (option != null) {
			return this.getAccessControlList(container, objectUri);
		}
		option = params.getFirst("metadata");
		if (option != null) {
			return this.getUserMetadata(container, objectUri);
		}

		return null;
	}

	@DELETE
	public Response deleteResource(@PathParam("container") String container,
			@PathParam("objectUri") String objectUri,
			@Context HttpHeaders headers, byte[] context) {
		return deleteObject(container, objectUri);
	}

	@HEAD
	public Response headResource(@PathParam("container") String container,
			@PathParam("objectUri") String objectUri,
			@Context HttpHeaders headers, byte[] context) {
		MultivaluedMap<String, String> params = ui.getQueryParameters();
		String option = params.getFirst("metadata");
		if (option != null) {
			return this.getUserMetadata(container, objectUri);
		}

		List<String> ls = headers
				.getRequestHeader(Headers.CDMI_REQUEST_METADATA);
		boolean withMetadata = false;
		if (ls != null && ls.size() > 0) {
			withMetadata = Boolean.valueOf(ls.get(0));
		}
		return getProperties(container, objectUri, withMetadata);
	}

	/**
	 * 存储数据：PUT /mycontainer/myobject HTTP/1.1
	 * 
	 * @param container
	 * @param objectUri
	 * @param prefix
	 *            (暂无用)
	 * @param md5
	 * @param stream
	 * @return
	 */
	@PUT
	@Produces("binary/octet-stream")
	public Response putObject(
			@PathParam("container") String container,
			@PathParam("objectUri") String objectUri,
			// @HeaderParam(Headers.CDMI_PREFIX) String prefix,
			@HeaderParam(Headers.CDMI_CONTENT_MD5) String md5,
			@HeaderParam(Headers.CDMI_SLICE_OFFSET) long offset,
			@HeaderParam(Headers.CDMI_ZIP_MODE) String zip,// 以何种方式进行压缩
			@HeaderParam(Headers.CDMI_CONTEXT_ENCRYPT) boolean encrypt,// 是否已加密
			InputStream stream) {

		System.out.println("invoke::" + "putObject");

		InputDataObject input = new InputDataObject();
		input.setAccessKey(this.getPrincipal().getIdentifier());
		input.setContainerName(container);
		input.setObjectUri(objectUri);
		// input.setPrefix(prefix);
		input.setContent(stream);
		input.setOffset(offset);
		input.setMd5(md5);
		// 设置对象的存储模式
		List<StoreClass> storeclasses = new ArrayList<StoreClass>();
		if (!StringUtils.isBlank(zip)) {
			input.setZipMode(ZipMode.valueOf(zip));
			storeclasses.add(StoreClass.Zip);
		}
		if (encrypt) {
			storeclasses.add(StoreClass.Encrypt);
		}
		input.setStoreClasses(storeclasses);

		compositor.createDataObject(input);
		return Response.ok().header(Headers.CDMI_VERSION, "1.0").build();
	}

	/**
	 * 分块存储数据：PUT /mycontainer/myobject?part HTTP/1.1
	 * 
	 * @param container
	 * @param objectUri
	 * @param prefix
	 * @param md5
	 * @param offset
	 * @param lastslice
	 * @param stream
	 * @return
	 */
	@PUT
	@QueryParam(QueryParameters.PART)
	@Produces(MediaTypes.DATA_OBJECT)
	@Consumes("binary/octet-stream")
	public Response putPartObject(
			@PathParam("container") String container,
			@PathParam("objectUri") String objectUri,
			// @HeaderParam(Headers.CDMI_PREFIX) String prefix,
			@HeaderParam(Headers.CDMI_CONTENT_MD5) String md5,
			@HeaderParam(Headers.CDMI_SLICE_OFFSET) String offset,
			@HeaderParam(Headers.CDMI_SLICE_LAST) boolean lastslice,
			@Context InputStream stream) {

		System.out.println("invoke::" + "putObjectSlice");

		throw new UnsupportedOperationException(
				"ObjectResource::putObjectSlice()");
	}

	/**
	 * 存储数据：POST /mycontainer/myobject HTTP/1.1
	 * 
	 * @param container
	 * @param objectUri
	 * @param prefix
	 * @param md5
	 * @param stream
	 * @return
	 */
	@POST
	@Produces("binary/octet-stream")
	@Consumes("xml/json")
	public Response postObject(@PathParam("container") String container,
			@PathParam("objectUri") String objectUri,
			// @FormParam(Headers.CDMI_PREFIX) String prefix,
			@FormParam(Headers.CDMI_CONTENT_MD5) String md5,
			@FormParam(Headers.CDMI_ZIP_MODE) String zip,// 以何种方式进行压缩
			@FormParam(Headers.CDMI_CONTEXT_ENCRYPT) boolean encrypt,// 是否已加密
			InputStream stream) {

		System.out.println("invoke::" + "postObject");

		InputDataObject input = new InputDataObject();
		input.setAccessKey(this.getPrincipal().getIdentifier());
		input.setContainerName(container);
		input.setObjectUri(objectUri);
		// input.setPrefix(prefix);
		input.setContent(stream);
		input.setMd5(md5);
		// 设置对象的存储模式
		List<StoreClass> storeclasses = new ArrayList<StoreClass>();
		if (!StringUtils.isBlank(zip)) {
			input.setZipMode(ZipMode.valueOf(zip));
			storeclasses.add(StoreClass.Zip);
		}
		if (encrypt) {
			storeclasses.add(StoreClass.Encrypt);
		}
		input.setStoreClasses(storeclasses);

		compositor.createDataObject(input);
		return Response.ok().header(Headers.CDMI_VERSION, "1.0").build();
	}

	/**
	 * 获取数据：GET /mycontainer/myobject HTTP/1.1
	 * 
	 * @param container
	 * @param objectUri
	 * @return
	 */
	@GET
	@Consumes("binary/octet-stream")
	public Response getObject(@PathParam("container") String container,
			@PathParam("objectUri") String objectUri) {

		System.out.println("invoke::" + "getObject");
		compositor.setAuthorization(this.getPrincipal());
		DataObject data = compositor.getDataObject(container, objectUri);
		return Response.ok(data.getContent()).type(data.getMimetype())
				.header(Headers.CDMI_VERSION, "1.0").build();
	}

	/**
	 * 分片获取数据：GET /mycontainer/myobject?slice HTTP/1.1
	 * 
	 * @param container
	 * @param objectUri
	 * @param offset
	 * @param length
	 * @return
	 */
	@GET
	@QueryParam(QueryParameters.PART)
	@Produces(MediaTypes.DATA_OBJECT)
	@Consumes("binary/octet-stream")
	public Response getPartObject(@PathParam("container") String container,
			@PathParam("objectUri") String objectUri,
			@HeaderParam(Headers.CDMI_SLICE_OFFSET) String offset,
			@HeaderParam(Headers.CDMI_SLICE_LENGTH) int length) {

		System.out.println("invoke::" + "getObjectSlice");
		throw new UnsupportedOperationException(
				"ObjectResource::getObjectSlice()");
	}

	/**
	 * 删除数据：DELETE /mycontainer/myobject HTTP/1.1
	 * 
	 * @param container
	 * @param objectUri
	 * @param offset
	 * @param length
	 * @return
	 */
	@DELETE
	private Response deleteObject(@PathParam("container") String container,
			@PathParam("objectUri") String objectUri) {

		System.out.println("invoke::" + "deleteObject");

		compositor.deleteDataObject(container, objectUri);
		return Response.ok().header(Headers.CDMI_VERSION, "1.0").build();
	}

	/**
	 * 设置数据的访问控制策略：PUT /mycontainer/myobject?acl HTTP/1.1
	 * 
	 * @param container
	 * @param objectUri
	 * @return
	 */
	@PUT
	@Produces(MediaTypes.ACL)
	@Consumes(MediaTypes.ACL)
	private Response setAccessControlPolicy(
			@PathParam("container") String container,
			@PathParam("objectUri") String objectUri, byte[] acl) {

		System.out.println("invoke::" + "setAccessControlPolicy");

		// 检查Container的格式是否正确
		// 如果不正确直接返回错误
		if (container == null || container.trim().length() < 1) {
			throw new BadRequestException(ErrorCodes.InvalidBucketName);
		}
		if (objectUri == null || objectUri.trim().length() < 1) {
			throw new BadRequestException(ErrorCodes.InvalidObjectURI);
		}

		AccessControlList acl_obj = new AccessControlList();
		acl_obj.fromJson(acl);

		compositor.setAccessControlPolicy(container, objectUri, acl_obj);
		return Response.ok().header(Headers.CDMI_VERSION, "1.0").build();
	}

	/**
	 * 获取数据访问控制策略：GET /mycontainer?acl HTTP/1.1
	 * 
	 * @param container
	 * @param objectUri
	 * @param acl
	 */
	@GET
	@QueryParam(QueryParameters.ACL)
	@Produces(MediaTypes.ACL)
	@Consumes(MediaTypes.ACL)
	private Response getAccessControlList(
			@PathParam("container") String container,
			@PathParam("objectUri") String objectUri) {

		System.out.println("invoke::" + "getAccessControlPolicy");

		compositor.setAuthorization(this.getPrincipal());
		Map<String, String> aclMap = compositor.getAccessControlList(container,
				objectUri);
		AccessControlList acl = new AccessControlList();

		for (Map.Entry<String, String> m : aclMap.entrySet()) {
			Grantee accesskey = new KeyGrantee();
			accesskey.setIdentifier(m.getKey());
			acl.grantPermission(accesskey, Permission.fromValue(m.getValue()));
		}
		// TODO 目前只能是请求者自己
		acl.setAccessKey(this.getPrincipal().getIdentifier());
		String owner = this.getPrincipal().getIdentifier();
		String respStr = acl.toJson(owner);
		return Response.ok(respStr).header(Headers.CDMI_VERSION, "1.0").build();
	}

	/**
	 * 设置对象元数据：PUT /mycontainer/myobject?metadata HTTP/1.1
	 * 
	 * @param container
	 * @param objectUri
	 * @param acl
	 */
	@PUT
	@QueryParam(QueryParameters.METADATA)
	@Produces(MediaTypes.METADATA)
	@Consumes(MediaTypes.METADATA)
	private Response setUserMetadata(@PathParam("container") String container,
			@PathParam("objectUri") String objectUri,
			@Context HttpHeaders metadata) {

		System.out.println("invoke::" + "setMetadata");

		Map<String, String> mapMeta = new HashMap<String, String>();
		for (String hdr : metadata.getRequestHeaders().keySet()) {
			System.out.println(hdr + " - " + metadata.getRequestHeader(hdr));
			if (hdr.startsWith(Headers.CDMI_USER_METADATA_PREFIX)) {
				String meta = hdr.substring(
						Headers.CDMI_USER_METADATA_PREFIX.length(),
						hdr.length());
				mapMeta.put(meta, metadata.getRequestHeader(hdr).get(0));
			}
		}

		if (mapMeta.size() != 0) {
			compositor.setUserMetadata(container, objectUri, mapMeta);
		}

		return Response.ok().header(Headers.CDMI_VERSION, "1.0").build();
	}

	/**
	 * 获取对象元数据：GET/HEAD /mycontainer/myobject?metadata HTTP/1.1
	 * 
	 * @param container
	 * @param objectUri
	 * @return
	 */
	@GET
	@HEAD
	private Response getUserMetadata(@PathParam("container") String container,
			@PathParam("objectUri") String objectUri) {

		System.out.println("invoke::" + "getMetadata");
		Map<String, String> mapMeta = compositor.getUserMetadata(container,
				objectUri);
		ResponseBuilder builder = Response.ok();
		for (Map.Entry<String, String> m : mapMeta.entrySet()) {
			builder.header(Headers.CDMI_USER_METADATA_PREFIX + m.getKey(),
					m.getValue());
		}
		return builder.header(Headers.CDMI_VERSION, "1.0").build();
	}

	/**
	 * 获取对象的属性：HAED /mycontainer/myobject HTTP/1.1
	 * 
	 * @param container
	 * @param objectUri
	 * @param withMetadata
	 * @return
	 */
	@HEAD
	private Response getProperties(@PathParam("container") String container,
			@PathParam("objectUri") String objectUri,
			@HeaderParam(Headers.CDMI_REQUEST_METADATA) boolean withMetadata) {

		System.out.println("invoke::" + "getProperties");

		DataObjectProperties props = compositor.getProperties(container,
				objectUri, withMetadata);
		Map<String, String> mapMeta = props.getUserMetadata();

		ResponseBuilder builder = Response.ok();
		for (Map.Entry<String, String> m : mapMeta.entrySet()) {
			builder.header(Headers.CDMI_USER_METADATA_PREFIX + m.getKey(),
					m.getValue());
		}

		return Response.ok().header(Headers.CDMI_VERSION, "1.0").build();
	}

	/**
	 * 复制数据：PUT /mycontainer/newobjecturi HTTP/1.1
	 * 
	 * @param container
	 * @param objectUri
	 * @param source
	 * @param replaceFlag
	 * @param prefix
	 * @param md5
	 * @param stream
	 * @return
	 */
	@PUT
	@HeaderParam(Headers.CDMI_COPY_SOURCE)
	private Response copyObject(@PathParam("container") String container,
			@PathParam("objectUri") String objectUri,
			@HeaderParam(Headers.CDMI_COPY_SOURCE) String source,
			// @HeaderParam(Headers.CDMI_CONTENT_MD5) String md5,
			// @HeaderParam(Headers.CDMI_PREFIX) String prefix,
			@HeaderParam(Headers.CDMI_METADATA_REPLACE) boolean replaceFlag) {

		System.out.println("invoke::" + "copyObject");

		MetaDataObject meta = compositor.copyDataObject(source, container,
				objectUri, replaceFlag);

		ResponseBuilder builder = Response.ok();
		builder.header(Headers.LAST_MODIFIED, meta.getCreationDate());
		return builder.header(Headers.CDMI_VERSION, "1.0").build();
	}

	// /*********************** 扩展：目录服务 ********************************/
	// /**
	// * 移动或重命名数据：PUT /mycontainer/Path HTTP/1.1
	// *
	// * @param container
	// * @param objectUri
	// * @param source
	// * @param prefix
	// * @param md5
	// * @return
	// */
	// @PUT
	// @HeaderParam(Headers.CDMI_MOVE_SOURCE)
	// public Response moveObject(@PathParam("container") String container,
	// @PathParam("objectUri") String objectUri,
	// @HeaderParam(Headers.CDMI_MOVE_SOURCE) String source,
	// // @HeaderParam(Headers.CDMI_PREFIX) String prefix,
	// @HeaderParam(Headers.CDMI_CONTENT_MD5) String md5) {
	//
	// System.out.println("invoke::" + "moveObject");
	// throw new UnsupportedOperationException("ObjectResource::moveObject()");
	// }
	//
	// /*********************** 扩展：公共文件访问服务 ************************/
	// /**
	// * 允许对象进行公共访问：PUT /mycontainer/myobject?public HTTP/1.1
	// *
	// * @param container
	// * @param objectUri
	// * @param prefix
	// * @param code
	// * @param limit
	// * @param date
	// * @return
	// */
	// @PUT
	// @QueryParam(QueryParameters.PUBLIC)
	// public Response setPublicObject(@PathParam("container") String container,
	// @PathParam("objectUri") String objectUri,
	// @HeaderParam(Headers.CDMI_PUBLIC_PREFIX) String prefix,
	// @HeaderParam(Headers.CDMI_PUBLIC_CODE) String code,
	// @HeaderParam(Headers.CDMI_PUBLIC_LIMIT_NUMBER) int limit,
	// @HeaderParam(Headers.CDMI_PUBLIC_INVALIDATION_DATE) Date date) {
	//
	// System.out.println("invoke::" + "setPublicObject");
	// throw new UnsupportedOperationException(
	// "ObjectResource::setPublicObject()");
	// }
	//
	// /**
	// * 禁止对象进行公共访问：DELETE /mycontainer/myobject?public HTTP/1.1
	// *
	// * @param container
	// * @param objectUri
	// * @return
	// */
	// @DELETE
	// @QueryParam(QueryParameters.PUBLIC)
	// public Response cancelPublicObject(
	// @PathParam("container") String container,
	// @PathParam("objectUri") String objectUri) {
	//
	// System.out.println("invoke::" + "cancelPublicObject");
	// throw new UnsupportedOperationException(
	// "ObjectResource::cancelPublicObject()");
	// }
	//
	// /**
	// * 获取对象的公共访问属性：HEAD /mycontainer/myobject?public HTTP/1.1
	// *
	// * @param container
	// * @param objectUri
	// * @return
	// */
	// @HEAD
	// @QueryParam(QueryParameters.PUBLIC)
	// public Response getPublicProperties(
	// @PathParam("container") String container,
	// @PathParam("objectUri") String objectUri) {
	//
	// System.out.println("invoke::" + "getPublicProperties");
	// throw new UnsupportedOperationException(
	// "ObjectResource::getPublicProperties()");
	// }
	//
	// /**
	// * 网页方式获取公共访问对象：GET /mycontainer/myobject?public&code=$code HTTP/1.1
	// *
	// * @param container
	// * @param objectUri
	// * @return
	// */
	// @GET
	// @QueryParam(QueryParameters.PUBLIC)
	// @Produces("application/zip")
	// public Response getPublicObject(@PathParam("container") String container,
	// @PathParam("objectUri") String objectUri,
	// @QueryParam(QueryParameters.PUBLIC_CODE) String code) {
	//
	// System.out.println("invoke::" + "getPublicObject");
	// throw new UnsupportedOperationException(
	// "ObjectResource::getPublicObject()");
	// }
	//
	// /*********************** 扩展：文件外链服务 ************************/
	//
	// /**
	// * 网页外链方式访问对象：Get /mycontainer/myobject?link HTTP/1.1
	// *
	// * @param container
	// * @param objectUri
	// * @return
	// */
	// @GET
	// @QueryParam(QueryParameters.LINK)
	// public Response getLinkObject(@PathParam("container") String container,
	// @PathParam("objectUri") String objectUri) {
	//
	// System.out.println("invoke::" + "getLinkObject");
	// throw new UnsupportedOperationException(
	// "ObjectResource::getLinkObject()");
	// }
	//
	// /**
	// * 网页外链方式访问图片的临时缩略图：Get
	// * /mycontainer/myobject？link&height=$height&width=$width&zoom=$scale
	// * HTTP/1.1
	// *
	// * @param container
	// * @param objectUri
	// * @param height
	// * @param width
	// * @param scale
	// * @return
	// */
	// @GET
	// @QueryParam(QueryParameters.LINK)
	// public Response getThumbnailObject(
	// @PathParam("container") String container,
	// @PathParam("objectUri") String objectUri,
	// @QueryParam(QueryParameters.THUMBNAIL_HEIGHT) int height,
	// @QueryParam(QueryParameters.THUMBNAIL_WIDTH) int width,
	// @QueryParam(QueryParameters.THUMBNAIL_ZOOM) String scale) {
	//
	// System.out.println("invoke::" + "getThumbnailObject");
	// throw new UnsupportedOperationException(
	// "ObjectResource::getThumbnailObject()");
	// }
	//
	// /*********************** 扩展数据服务：文件格式转换 ************************/
	//
	// /**
	// * 数据格式转换：PUT /mycontainer/myobject HTTP/1.1
	// *
	// * @param container
	// * @param objectUri
	// * @param source
	// * @param deleteFlag
	// * @param task
	// * @param prefix
	// * @return
	// */
	// @PUT
	// @HeaderParam(Headers.CDMI_CONVERTER_SOURCE)
	// public Response formatConverter(@PathParam("container") String container,
	// @PathParam("objectUri") String objectUri,
	// // @HeaderParam(Headers.CDMI_PREFIX) String prefix,
	// @HeaderParam(Headers.CDMI_CONVERTER_SOURCE) String source,
	// @HeaderParam(Headers.CDMI_CONVERTER_DELETE) boolean deleteFlag,
	// @HeaderParam(Headers.CDMI_TASK_PREFIX) String task ) {
	//
	// System.out.println("invoke::" + "formatConverter");
	// throw new UnsupportedOperationException(
	// "ObjectResource::formatConverter()");
	// }
	//
	// /*********************** 扩展数据服务：生成图片缩略图 ************************/
	//
	// /**
	// * 生成图片缩略图：PUT /mycontainer/myobject HTTP/1.1
	// *
	// * @param container
	// * @param objectUri
	// * @param source
	// * @param height
	// * @param width
	// * @param scale
	// * @param prefix
	// * @return
	// */
	// @PUT
	// @HeaderParam(Headers.CDMI_THUMBNAIL_SOURCE)
	// public Response buildThumbnail(@PathParam("container") String container,
	// @PathParam("objectUri") String objectUri,
	// // @HeaderParam(Headers.CDMI_PREFIX) String prefix,
	// @HeaderParam(Headers.CDMI_THUMBNAIL_SOURCE) String source,
	// @HeaderParam(Headers.CDMI_THUMBNAIL_HEIGHT) int height,
	// @HeaderParam(Headers.CDMI_THUMBNAIL_WIDTH) int width,
	// @HeaderParam(Headers.CDMI_THUMBNAIL_ZOOM) String scale) {
	//
	// System.out.println("invoke::" + "buildThumbnail");
	// throw new UnsupportedOperationException(
	// "ObjectResource::buildThumbnail()");
	// }
	//
	// /*********************** 扩展数据服务：离线下载 ************************/
	//
	// /**
	// * 离线下载文件：PUT /mycontainer/myobject HTTP/1.1
	// *
	// * @param container
	// * @param objectUri
	// * @param source
	// * @param task
	// * @param prefix
	// * @return
	// */
	// @PUT
	// @HeaderParam(Headers.CDMI_DOWNLOAD_SOURCE)
	// public Response offlineDownload(@PathParam("container") String container,
	// @PathParam("objectUri") String objectUri,
	// // @HeaderParam(Headers.CDMI_PREFIX) String prefix,
	// @HeaderParam(Headers.CDMI_DOWNLOAD_SOURCE) String source,
	// @HeaderParam(Headers.CDMI_TASK_PREFIX) String task) {
	//
	// System.out.println("invoke::" + "offlineDownload");
	// throw new UnsupportedOperationException(
	// "ObjectResource::offlineDownload()");
	// }
}
